package com.lyf.scm.plan.domain.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.lyf.scm.common.enums.PurchaseOrderTargetEnum;
import com.lyf.scm.common.enums.SkuUnitTypeEnum;
import com.lyf.scm.plan.api.dto.*;
import com.lyf.scm.plan.domain.remote.purchase.facade.PurchaseFacade;
import com.lyf.scm.plan.domain.service.PurchaseTargetService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * 采购中心批量指标获取
 *
 * @author wangchlei
 * @date 2020/11/22
 */
@Slf4j
@Service
public class PurchaseTargetServiceImpl implements PurchaseTargetService {
    @Resource
    private PurchaseFacade purchaseFacade;

    @Override
    public OtherTargetResultDTO getResult(OtherTargetGeneralQueryDTO otherTargetGeneralQueryDTO, Map<String, BigDecimal> unitMap) {
        return null;
    }

    @Override
    public List<OtherTargetResultDTO> getBatchResult(OtherTargetGeneralQueryDTO otherTargetGeneralQueryDTO, Map<String, BigDecimal> unitMap) {
        List<PoQtyQueryDTO> poQtyQueryDTOS = otherTargetGeneralQueryDTO.getPoQtyQueryDTOS();
        List<String> dateList = otherTargetGeneralQueryDTO.getDateList();
        List<Date> dates = this.transferToDate(dateList);
        List<OtherTargetResultDTO> list = defultValue();
        Long unitType = otherTargetGeneralQueryDTO.getUnitType();
        if (CollectionUtils.isNotEmpty(poQtyQueryDTOS)) {
            List<PoQtyDTO> poQtyDTOS;
            for (PoQtyQueryDTO poQtyQueryDTO : poQtyQueryDTOS) {
                poQtyDTOS = purchaseFacade.poQtyByWarehouseCodeAndSkuCode(poQtyQueryDTO);
                if (CollectionUtils.isNotEmpty(poQtyDTOS)) {
                    //仓库+sku分组    按照日期填充集合
                    Map<String, List<List<BigDecimal>>> resultMap = poQtyDTOS.stream().collect(groupingBy(item -> item.getWarehouseCode() + item.getSkuCode(), Collectors.collectingAndThen(Collectors.toList(), values -> {
                        List<List<BigDecimal>> lists = new ArrayList<>();
                        Map<Date, List<BigDecimal>> subResultMap = values.stream().collect(groupingBy(element -> DateUtil.beginOfWeek(element.getArrivalDate()), Collectors.collectingAndThen(Collectors.toList(), subValues -> {
                            List<BigDecimal> subLists = new ArrayList<>();
                            BigDecimal b1 = BigDecimal.ZERO;
                            BigDecimal b2 = BigDecimal.ZERO;
                            BigDecimal b3 = BigDecimal.ZERO;
                            BigDecimal b4 = BigDecimal.ZERO;
                            BigDecimal b5 = BigDecimal.ZERO;
                            for (PoQtyDTO poQtyDTO : subValues) {
                                if (poQtyDTO.getConfirmQty() != null) {
                                    b1 = b1.add(poQtyDTO.getConfirmQty());
                                }
                                if (poQtyDTO.getOnroadQty() != null) {
                                    b2 = b2.add(poQtyDTO.getOnroadQty());
                                }
                                if (poQtyDTO.getOrderQty() != null) {
                                    b3 = b3.add(poQtyDTO.getOrderQty());
                                }
                                if (poQtyDTO.getOriginalOrderQty() != null) {
                                    b4 = b4.add(poQtyDTO.getOriginalOrderQty());
                                }
                                if (poQtyDTO.getReceivedQty() != null) {
                                    b5 = b5.add(poQtyDTO.getReceivedQty());
                                }
                            }
                            //处理单位,非采购单位
                            if (!SkuUnitTypeEnum.PURCHASE_UNIT.getUnitType().equals(unitType)) {
                                String skuCode = subValues.get(0).getSkuCode();
                                BigDecimal scale = unitMap.get(skuCode + SkuUnitTypeEnum.PURCHASE_UNIT.getUnitType() + unitType);
                                subLists.add(b1.multiply(scale).setScale(3,BigDecimal.ROUND_HALF_UP));
                                subLists.add(b2.multiply(scale).setScale(3,BigDecimal.ROUND_HALF_UP));
                                subLists.add(b3.multiply(scale).setScale(3,BigDecimal.ROUND_HALF_UP));
                                subLists.add(b4.multiply(scale).setScale(3,BigDecimal.ROUND_HALF_UP));
                                subLists.add(b3.subtract(b2).subtract(b5).multiply(scale).setScale(3,BigDecimal.ROUND_HALF_UP));
                            } else {
                                subLists.add(b1);
                                subLists.add(b2);
                                subLists.add(b3);
                                subLists.add(b4);
                                subLists.add(b3.subtract(b2).subtract(b5));
                            }
                            return subLists;
                        })));
                        List<BigDecimal> l1 = new ArrayList<>();
                        List<BigDecimal> l2 = new ArrayList<>();
                        List<BigDecimal> l3 = new ArrayList<>();
                        List<BigDecimal> l4 = new ArrayList<>();
                        List<BigDecimal> l5 = new ArrayList<>();
                        for (Date date : dates) {
                            if (subResultMap.get(date) != null) {
                                l1.add(subResultMap.get(date).get(0));
                                l2.add(subResultMap.get(date).get(1));
                                l3.add(subResultMap.get(date).get(2));
                                l4.add(subResultMap.get(date).get(3));
                                l5.add(subResultMap.get(date).get(4));
                            } else {
                                l1.add(BigDecimal.ZERO);
                                l2.add(BigDecimal.ZERO);
                                l3.add(BigDecimal.ZERO);
                                l4.add(BigDecimal.ZERO);
                                l5.add(BigDecimal.ZERO);
                            }
                        }
                        lists.add(l1);
                        lists.add(l2);
                        lists.add(l3);
                        lists.add(l4);
                        lists.add(l5);
                        return lists;
                    })));
                    OtherTargetResultDTO otherTargetResultDTO1 = list.get(0);
                    OtherTargetResultDTO otherTargetResultDTO2 = list.get(1);
                    OtherTargetResultDTO otherTargetResultDTO3 = list.get(2);
                    OtherTargetResultDTO otherTargetResultDTO4 = list.get(3);
                    OtherTargetResultDTO otherTargetResultDTO5 = list.get(4);
                    String key;
                    List<List<BigDecimal>> value;
                    for (Map.Entry<String, List<List<BigDecimal>>> item : resultMap.entrySet()) {
                        key = item.getKey();
                        value = item.getValue();
                        otherTargetResultDTO1.getResult().put(key, value.get(0));
                        otherTargetResultDTO2.getResult().put(key, value.get(1));
                        otherTargetResultDTO3.getResult().put(key, value.get(2));
                        otherTargetResultDTO4.getResult().put(key, value.get(3));
                        otherTargetResultDTO5.getResult().put(key, value.get(4));
                    }
                }
            }
        }
        return list;
    }

    private List<Date> transferToDate(List<String> dateList) {
        List<Date> dates = new ArrayList<>();
        for (String dateStr : dateList) {
            dates.add(DateUtil.parse(dateStr, DatePattern.NORM_DATE_PATTERN));
        }
        return dates;
    }

    /**
     * 初始值
     *
     * @param
     * @return {@link List<OtherTargetResultDTO>}
     **/
    private List<OtherTargetResultDTO> defultValue() {
        List<OtherTargetResultDTO> list = new ArrayList<>();
        //赋初始值
        OtherTargetResultDTO otherTargetResultDTO1 = new OtherTargetResultDTO();
        otherTargetResultDTO1.setOtherTargetsEnum(PurchaseOrderTargetEnum.CONFIRMED_PURCHASE_ORDERS);
        Map<String, List<BigDecimal>> result1 = new HashMap<>();
        otherTargetResultDTO1.setResult(result1);
        OtherTargetResultDTO otherTargetResultDTO2 = new OtherTargetResultDTO();
        otherTargetResultDTO2.setOtherTargetsEnum(PurchaseOrderTargetEnum.APPOINTMENT_PURCHASE_QUANTITY);
        Map<String, List<BigDecimal>> result2 = new HashMap<>();
        otherTargetResultDTO2.setResult(result2);
        OtherTargetResultDTO otherTargetResultDTO3 = new OtherTargetResultDTO();
        otherTargetResultDTO3.setOtherTargetsEnum(PurchaseOrderTargetEnum.PURCHASE_ORDER_QUANTITY);
        Map<String, List<BigDecimal>> result3 = new HashMap<>();
        otherTargetResultDTO3.setResult(result3);
        OtherTargetResultDTO otherTargetResultDTO4 = new OtherTargetResultDTO();
        otherTargetResultDTO4.setOtherTargetsEnum(PurchaseOrderTargetEnum.PURCHASE_PLAN_QUANTITY);
        Map<String, List<BigDecimal>> result4 = new HashMap<>();
        otherTargetResultDTO4.setResult(result4);
        OtherTargetResultDTO otherTargetResultDTO5 = new OtherTargetResultDTO();
        otherTargetResultDTO5.setOtherTargetsEnum(PurchaseOrderTargetEnum.UNFULFILLED_PURCHASE_QUANTITY);
        Map<String, List<BigDecimal>> result5 = new HashMap<>();
        otherTargetResultDTO5.setResult(result5);
        list.add(otherTargetResultDTO1);
        list.add(otherTargetResultDTO2);
        list.add(otherTargetResultDTO3);
        list.add(otherTargetResultDTO4);
        list.add(otherTargetResultDTO5);
        return list;
    }

    @Override
    public OtherTargetEchartResultDTO getEchartResult(OtherTargetGeneralQueryDTO otherTargetGeneralQueryDTO) {
        return null;
    }

    @Override
    public List<OtherTargetEchartResultDTO> getBatchEchartResult(OtherTargetGeneralQueryDTO otherTargetGeneralQueryDTO) {
        PoQtyAggregationQueryDTO poQtyAggregationQueryDTO = otherTargetGeneralQueryDTO.getPoQtyAggregationQueryDTOs();
        List<String> dateList = otherTargetGeneralQueryDTO.getDateList();
        List<Date> dates = this.transferToDate(dateList);
        List<OtherTargetEchartResultDTO> list = defultEchartValue();
        if (poQtyAggregationQueryDTO != null) {
            List<PoQtyDTO> poQtyDTOS = purchaseFacade.aggregationPoQty(poQtyAggregationQueryDTO);
            if (CollectionUtils.isNotEmpty(poQtyDTOS)) {
                //仓库+sku分组    按照日期填充集合
                Map<Date, List<BigDecimal>> subResultMap = poQtyDTOS.stream().collect(groupingBy(element -> DateUtil.beginOfWeek(element.getArrivalDate()), Collectors.collectingAndThen(Collectors.toList(), subValues -> {
                    List<BigDecimal> subLists = new ArrayList<>();
                    BigDecimal b1 = BigDecimal.ZERO;
                    BigDecimal b2 = BigDecimal.ZERO;
                    BigDecimal b3 = BigDecimal.ZERO;
                    BigDecimal b4 = BigDecimal.ZERO;
                    BigDecimal b5 = BigDecimal.ZERO;
                    for (PoQtyDTO poQtyDTO : subValues) {
                        if (poQtyDTO.getConfirmQty() != null) {
                            b1 = b1.add(poQtyDTO.getConfirmQty());
                        }
                        if (poQtyDTO.getOnroadQty() != null) {
                            b2 = b2.add(poQtyDTO.getOnroadQty());
                        }
                        if (poQtyDTO.getOrderQty() != null) {
                            b3 = b3.add(poQtyDTO.getOrderQty());
                        }
                        if (poQtyDTO.getOriginalOrderQty() != null) {
                            b4 = b4.add(poQtyDTO.getOriginalOrderQty());
                        }
                        if (poQtyDTO.getReceivedQty() != null) {
                            b5 = b5.add(poQtyDTO.getReceivedQty());
                        }
                    }
                    subLists.add(b1);
                    subLists.add(b2);
                    subLists.add(b3);
                    subLists.add(b4);
                    subLists.add(b3.subtract(b2).subtract(b5));
                    return subLists;
                })));
                List<BigDecimal> l1 = new ArrayList<>();
                List<BigDecimal> l2 = new ArrayList<>();
                List<BigDecimal> l3 = new ArrayList<>();
                List<BigDecimal> l4 = new ArrayList<>();
                List<BigDecimal> l5 = new ArrayList<>();
                for (Date date : dates) {
                    if (subResultMap.get(date) != null) {
                        l1.add(subResultMap.get(date).get(0));
                        l2.add(subResultMap.get(date).get(1));
                        l3.add(subResultMap.get(date).get(2));
                        l4.add(subResultMap.get(date).get(3));
                        l5.add(subResultMap.get(date).get(4));
                    } else {
                        l1.add(BigDecimal.ZERO);
                        l2.add(BigDecimal.ZERO);
                        l3.add(BigDecimal.ZERO);
                        l4.add(BigDecimal.ZERO);
                        l5.add(BigDecimal.ZERO);
                    }
                }
                list.get(0).setResult(l1);
                list.get(1).setResult(l2);
                list.get(2).setResult(l3);
                list.get(3).setResult(l4);
                list.get(4).setResult(l5);
            }
        }
        return list;
    }

    /**
     * 初始值
     *
     * @param
     * @return {@link List<OtherTargetResultDTO>}
     **/
    private List<OtherTargetEchartResultDTO> defultEchartValue() {
        List<OtherTargetEchartResultDTO> list = new ArrayList<>();
        //赋初始值
        OtherTargetEchartResultDTO otherTargetResultDTO1 = new OtherTargetEchartResultDTO();
        otherTargetResultDTO1.setOtherTargetsEnum(PurchaseOrderTargetEnum.CONFIRMED_PURCHASE_ORDERS);
        List<BigDecimal> result1 = new ArrayList<>();
        otherTargetResultDTO1.setResult(result1);
        OtherTargetEchartResultDTO otherTargetResultDTO2 = new OtherTargetEchartResultDTO();
        otherTargetResultDTO2.setOtherTargetsEnum(PurchaseOrderTargetEnum.APPOINTMENT_PURCHASE_QUANTITY);
        List<BigDecimal> result2 = new ArrayList<>();
        otherTargetResultDTO2.setResult(result2);
        OtherTargetEchartResultDTO otherTargetResultDTO3 = new OtherTargetEchartResultDTO();
        otherTargetResultDTO3.setOtherTargetsEnum(PurchaseOrderTargetEnum.PURCHASE_ORDER_QUANTITY);
        List<BigDecimal> result3 = new ArrayList<>();
        otherTargetResultDTO3.setResult(result3);
        OtherTargetEchartResultDTO otherTargetResultDTO4 = new OtherTargetEchartResultDTO();
        otherTargetResultDTO4.setOtherTargetsEnum(PurchaseOrderTargetEnum.PURCHASE_PLAN_QUANTITY);
        List<BigDecimal> result4 = new ArrayList<>();
        otherTargetResultDTO4.setResult(result4);
        OtherTargetEchartResultDTO otherTargetResultDTO5 = new OtherTargetEchartResultDTO();
        otherTargetResultDTO5.setOtherTargetsEnum(PurchaseOrderTargetEnum.UNFULFILLED_PURCHASE_QUANTITY);
        List<BigDecimal> result5 = new ArrayList<>();
        otherTargetResultDTO5.setResult(result5);
        list.add(otherTargetResultDTO1);
        list.add(otherTargetResultDTO2);
        list.add(otherTargetResultDTO3);
        list.add(otherTargetResultDTO4);
        list.add(otherTargetResultDTO5);
        return list;
    }
}
